use std::{vec, str};
use redis_protocol::resp2::prelude::*;

#[derive(Debug)]
pub struct FrameParser {
    inner: vec::IntoIter<Frame>
}
#[derive(Debug)]
pub enum ParseErr {
    EndOfStream,
    UNEXPECTED,
}
impl FrameParser {
    pub fn new(f: Frame) -> Result<Self, ParseErr> {
        match f {
            Frame::Array(arr) => Ok(FrameParser { inner: arr.into_iter() }),
            _ => Err(ParseErr::UNEXPECTED)
        }
    }
    pub fn next_string(&mut self) -> Result<String, ParseErr> {
        let n = self.inner.next();
        if n.is_none() {
            return Err(ParseErr::EndOfStream);
        }
        match n.unwrap(){
            Frame::SimpleString(s) => Ok(s),
            Frame::BulkString(s) => str::from_utf8(&s).
                map_err(|_e|ParseErr::UNEXPECTED).map(|v|v.to_string()),
            _ => todo!()
        }
    }
}

#[derive(Debug)]
pub struct FrameConstructor {
    inner: Frame
}

impl FrameConstructor {
    pub fn new() -> Self {
        FrameConstructor { inner: Frame::Array(Vec::<Frame>::new()) }
    }
    pub fn append_string(&mut self, s: &str) {
        let f = Frame::BulkString(Vec::from(s));
        match &mut self.inner {
            Frame::Array(arr) => arr.push(f),
            _ => panic!("Error, unexpected type")
        };
    }

    pub fn construct_frame(&self) -> Frame {
        self.inner.clone()
    }
    pub fn ok() -> Frame {
        Frame::SimpleString("ok".to_string())
    }
    pub fn err() -> Frame {
        Frame::Integer(0)
    }
}